#include "HuffmanTreeFunction.hpp"
#include <cstring>
#include <regex>

using namespace std;

int testByInput(Code arrSrc[]) {
    // 输入初始化
    int size = 0;
    cout << "size?" << endl;
    cin >> size;
    Code arr[size];
    for (int i = 0; i < size; i++) {
        // 输入字符并参数校验
        cout << "the " + to_string(i + 1) + " character" << endl;
        string character;
        regex patternCharacter("[a-zA-Z]");
        smatch resultCharacter;
        cin >> character;
        while (!regex_match(character, resultCharacter, patternCharacter)) {
            cout << "please input the " + to_string(i + 1) + " character again" << endl;
            cin >> character;
        }
        arr[i].character = character.at(0);

        // 输入权重并参数校验
        cout << "the " + to_string(i + 1) + " weight" << endl;
        string weight;
        cin >> weight;
        regex patternWeight("\\d+");
        smatch resultWeight;
        while (!regex_match(weight, resultWeight, patternWeight)) {
            cout << "please input the " + to_string(i + 1) + " weight again" << endl;
            cin >> weight;
        }
        arr[i].weight = stoi(weight);
    }
    copy(arr, arr + size, arrSrc);
    return size;
}

int testByInit(Code arrSrc[]) {
    // 手动初始化
    Code arr[] = {{'A', 20},
                  {'B', 17},
                  {'C', 6},
                  {'D', 8},
                  {'E', 11},
                  {'F', 8},
                  {'G', 5},
                  {'H', 8},
                  {'I', 13},
                  {'J', 3},
                  {'K', 1}};
    int size = sizeof(arr) / sizeof(arr[0]);
    for (int i = 0; i < size; i++) {
        arr[i].isMatched = false;
    }
    copy(arr, arr + size, arrSrc);
    return size;
}

int testByReadFile(Code arrSrc[]) {
    // 读取文件初始化
    int size = getHfmTreeSize();
    Code arr[size];
    readFromFile(arr, size);
    copy(arr, arr + size, arrSrc);
    return size;
}


int main() {
    Code arr[1000];
    // 选择以下两种方式中任选一种进行哈夫曼树的生成
    int size = testByInit(arr);
    // int size = testByInput(arr);

    int intArr[30];
    getNumArr(arr, intArr, size);

    // 生成帮助链表
    HelpNode *helpList = getHelpList(intArr, size);

    // 生成哈夫曼树
    Node *huffmanTree = createHuffmanTree(helpList);

    // 遍历哈夫曼树并编码
    codeTree(arr, huffmanTree, size, "");

    // 写入文件
    writeToFile(arr, size);

    // 打印哈夫曼树
    printTree(huffmanTree, 0, 0);

    // // 直接从文件中读取编码结果，无需再次生成，使用此方法前，先运行其他方法来生成数据文件
    // int size = testByReadFile(arr);

    // 将一串字符编码
    char str[] = "AEFIJWKDCB";
    for (int i = 0; i < strlen(str); i++) {
        encode(arr, str[i], size);
    }

    // 将码转为字符
    string num[] = {"01", "111", "1101", "001", "00000", "0000001", "0001"};
    for (const auto &i: num) {
        char character = decode(arr, i, size);
        if (character != '\0') {
            cout << character << endl;
        }
    }
    return 0;
}